package handlers

import (
	"fmt"
	"net/http"

	"github.com/gofiber/fiber/v2"
	"github.com/kadycui/fiber-ci/database"
	"github.com/kadycui/fiber-ci/models"
)

// GetAllProducts is a function to get all product data from database
// @Summary 查询全部产品
// @Description 查询全部产品
// @Tags Product
// @Accept json
// @Produce json
// @Success 200 {object} ResponseHTTP{data=[]models.Product}
// @Failure 503 {object} ResponseHTTP{}
// @Router /v1/product [get]
func GetAllProduct(c *fiber.Ctx) error {
	db := database.DBConn

	var products []models.Product
	if res := db.Find(&products); res.Error != nil {
		return c.Status(http.StatusServiceUnavailable).JSON(ResponseHTTP{
			Success: false,
			Message: res.Error.Error(),
			Data:    nil,
		})
	}

	return c.JSON(ResponseHTTP{
		Success: true,
		Message: "Success get all product.",
		Data:    products,
	})
}

// GetProductByID is a function to get a product by ID
// @Summary 通过ID获取一个产品
// @Description 通过ID获取一个产品
// @Tags Product
// @Accept json
// @Produce json
// @Param id path int true "Product ID"
// @Success 200 {object} ResponseHTTP{data=[]models.Product}
// @Failure 404 {object} ResponseHTTP{}
// @Failure 503 {object} ResponseHTTP{}
// @Router /v1/product/{id} [get]
func GetProductID(c *fiber.Ctx) error {
	id := c.Params("id")
	db := database.DBConn

	product := new(models.Product)
	if err := db.First(&product, id).Error; err != nil {
		switch err.Error() {
		case "record not found":
			return c.Status(http.StatusNotFound).JSON(ResponseHTTP{
				Success: false,
				Message: fmt.Sprintf("Product with ID %v not found.", id),
				Data:    nil,
			})
		default:
			return c.Status(http.StatusServiceUnavailable).JSON(ResponseHTTP{
				Success: false,
				Message: err.Error(),
				Data:    nil,
			})

		}
	}

	return c.JSON(ResponseHTTP{
		Success: true,
		Message: "Success get product by ID.",
		Data:    *product,
	})
}

// RegisterProduct registers a new product data
// @Summary 注册一个新的产品
// @Description 注册产品
// @Tags Product
// @Accept json
// @Produce json
// @Param product body models.BodyProduct true "Register product"
// @Success 200 {object} ResponseHTTP{data=models.Product}
// @Failure 400 {object} ResponseHTTP{}
// @Router /v1/product [post]
func RegisterProduct(c *fiber.Ctx) error {
	db := database.DBConn

	bodyProduct := new(models.BodyProduct)
	if err := c.BodyParser(&bodyProduct); err != nil {
		return c.Status(http.StatusBadRequest).JSON(ResponseHTTP{
			Success: false,
			Message: err.Error(),
			Data:    nil,
		})
	}

	product := models.Product{
		Title: bodyProduct.Title,
		Description: bodyProduct.Description,
		Amount: bodyProduct.Amount,
	}

	db.Create(&product)

	return c.JSON(ResponseHTTP{
		Success: true,
		Message: "Success register a product.",
		Data:    product,
	})
}

// DeleteProduct function removes a product by ID
// @Summary 通过ID移除产品
// @Description 通过ID移除产品
// @Tags Product
// @Accept json
// @Produce json
// @Param id path int true "Product ID"
// @Success 200 {object} ResponseHTTP{}
// @Failure 404 {object} ResponseHTTP{}
// @Failure 503 {object} ResponseHTTP{}
// @Router /v1/product/{id} [delete]
func DeleteProduct(c *fiber.Ctx) error {
	id := c.Params("id")
	db := database.DBConn

	product := new(models.Product)
	if err := db.First(&product, id).Error; err != nil {
		switch err.Error() {
		case "record not found":
			return c.Status(http.StatusNotFound).JSON(ResponseHTTP{
				Success: false,
				Message: fmt.Sprintf("bodyProduct with ID %v not found.", id),
				Data:    nil,
			})
		default:
			return c.Status(http.StatusServiceUnavailable).JSON(ResponseHTTP{
				Success: false,
				Message: err.Error(),
				Data:    nil,
			})

		}
	}

	db.Delete(&product)

	return c.JSON(ResponseHTTP{
		Success: true,
		Message: "Success delete product.",
		Data:    nil,
	})
}

// UpdateProduct function update a product by ID
// @Summary 通过ID更新产品
// @Description 通过ID更新产品
// @Tags Product
// @Accept json
// @Produce json
// @Param id path int true "Product ID"
// @Param product body models.BodyProduct true "Register product"
// @Success 200 {object} ResponseHTTP{}
// @Failure 404 {object} ResponseHTTP{}
// @Failure 503 {object} ResponseHTTP{}
// @Router /v1/product/{id} [put]
func UpdateProduct(c *fiber.Ctx) error {
	id := c.Params("id")
	db := database.DBConn

	product := new(models.Product)
	if err := db.First(&product, id).Error; err != nil {
		switch err.Error() {
		case "record not found":
			return c.Status(http.StatusNotFound).JSON(ResponseHTTP{
				Success: false,
				Message: fmt.Sprintf("Product with ID %v not found.", id),
				Data:    nil,
			})
		default:
			return c.Status(http.StatusServiceUnavailable).JSON(ResponseHTTP{
				Success: false,
				Message: err.Error(),
				Data:    nil,
			})

		}
	}

	bodyProduct := new(models.BodyProduct)
	if err := c.BodyParser(&bodyProduct); err != nil {
		return c.Status(http.StatusBadRequest).JSON(ResponseHTTP{
			Success: false,
			Message: err.Error(),
			Data:    nil,
		})
	}

	product.Title = bodyProduct.Title
	product.Description = bodyProduct.Description
	product.Amount = bodyProduct.Amount

	db.Save(&product)

	return c.JSON(ResponseHTTP{
		Success: true,
		Message: "Success update a product.",
		Data:    product,
	})
}
